package pip.can;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;




public class Simulator {
	private HashMap<String, Node> topology;
	private int[] Results;
	private double[] Mean;
	public double time;
	/**
	 * Lista zdarzen
	 */
	public LinkedList<Event> EventQueue;
	/**
	 * konstruktor
	 */
	public Simulator(HashMap<String, Node> topo)
	{
		topology=topo;
		EventQueue = new LinkedList<Event>();
		Results= new int[StaticVariables.Classes];
		Mean= new double[StaticVariables.Classes];
		time=0;
	}
	public void addResult(double res, int c)
	{
//		System.out.println("obecny wynik to "+Mean[c]+" a ilosc wynikow to "+Results[c]);
		Mean[c]=(Mean[c]*Results[c]+res)/(double)(Results[c]+1);
		Results[c]++;
//		System.out.println("po korekcie wynik to "+Mean[c]+" a ilosc wynikow to "+Results[c]+" a klasa ruchu to "+c);
		
	}
	public void addRequest(String who, int ContentId, int TrafficClass, double time)
	{
		this.addEvent(new Event(EventType.Arrival,time,who,new Message(ContentId, 0, TrafficClass, time)));
	}
	/**
	 * Dodaj event do listy zdarzen
	 */
	public void addEvent(Event e)
	{
		EventQueue.add(e);
		Collections.sort(EventQueue, new EventComparator());
	}
	/**
	 * pobierz nastepny event
	 */
	public Event getEvent()
	{
		if(! EventQueue.isEmpty())
		{
			Event tmp=EventQueue.removeFirst();
			time=tmp.time;
			return tmp;
		}
		else{
			return null;
		}
	}
	/**
	 * czy lista zdarzen jest pusta
	 */
	public boolean empty()
	{
		if(EventQueue.isEmpty())
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	public void start()
	{
		Event tmp=this.getEvent();
		while(tmp!=null && !StaticVariables.end)  
		{
			if(tmp.time>StaticVariables.endTime)
			{
				break;
			}
			if(tmp.type==EventType.Arrival)
			{
				//System.out.println("jest zdarzenie typu arrival"+time*1e6+" w wezle "+tmp.node);
				topology.get(tmp.node).addPacket(tmp.Message,this);
			}
			else if(tmp.type==EventType.Departure)
			{
				//System.out.println("jest zdarzenie typu departure t="+time*1e6+ " w wezle "+tmp.node);
				topology.get(tmp.node).sendPacket(topology, this);
			}
			else if(tmp.type==EventType.BufferEmpty)
			{
				StaticVariables.progressBar.setValue((int)Math.ceil(tmp.time*100/StaticVariables.endTime));
				//System.out.println("jest zdarzenie typu buffer empty t="+time*1e6+ " w wezle "+tmp.node);
				if(topology.get(tmp.node).buffersempty())
				{
					topology.get(tmp.node).busy=false;
				}
				else
				{
					topology.get(tmp.node).sendPacket(topology, this);
				}
			}
			tmp=this.getEvent();
		}
		System.out.println("symulacja zakończona, ustawiam wyniki");
		StaticVariables.setResults(this.Mean);
	}
}
